// Author: Zhang Yisong(zhang_yisong@foxmail.com)
#pragma once

#include "allocator.hpp"
#include "async_result.hpp"
#include "async_task.hpp"
#include "awaitable.hpp"
#include "context.hpp"
#include "dispatcher.hpp"
#include "event.hpp"
#include "runnable.hpp"
#include "timer.hpp"
#include "whenAll.hpp"
#include "whenAny.hpp"
namespace coro {

using pw::OkStatus;
using pw::Status;

#define __CORO_CONSTRUCTOR_IMPL                                                \
: m_ctx{alloc} {       d.Post(m_entry);           }

#if CONFIG_CORO_GLOBAL_BUFF
#define CORO_CONSTRUCTOR(class_name)                                           \
public:                                                                        \
  class_name(coro::Dispatcher &d,                                              \
             pw::allocator::Allocator &alloc = coro::GetGlobalAllocator())     \
      __CORO_CONSTRUCTOR_IMPL
#else
#define CORO_CONSTRUCTOR(class_name)                                           \
public:                                                                        \
  class_name(coro::Dispatcher &d, pw::allocator::Allocator &alloc)             \
      __CORO_CONSTRUCTOR_IMPL
#endif

#define __CO_ETY(index, ctx, co_task) co_task(ctx)
#define __CO_ETY_SEP(index, co_task) ,
#define __CO_ETY_APPLY(ctx, ...)                                               \
  PW_APPLY(__CO_ETY, __CO_ETY_SEP, ctx, __VA_ARGS__)

#define CORO_CTX_ENRTY(...)                                                    \
  coro::Context m_ctx;                                                         \
  coro::Coro[PW_MACRO_ARG_COUNT(__VA_ARGS__)] m_entry{                         \
      __CO_ETY_APPLY(m_ctx, __VA_ARGS__)};

} // namespace coro